#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

// 用标准IO实现文件拷贝

int main(int argc, char const *argv[]) // ./copy  a.txt  b.txt
{
    // 0. 检查参数
    if(argc != 3)
    {
        printf("Usage: %s <src> <dst>\n", argv[0]);
        return 1;
    }

    // 1. 只读打开源文件、只写目标文件（若不存在则创建，若存在则清空）
    FILE *fp1 = fopen(argv[1], "r");
    FILE *fp2 = fopen(argv[2], "w");
    if(fp1 == NULL || fp2 == NULL)
    {
        perror("打开文件失败");
        return -1;
    }

    // 2. 循环读取源文件并放入目标文件
    char *buf = calloc(5, 20); // 分配了100字节
    while(1)
    {
        // 读取源文件
        // 返回值n代表读取到的数据块的块数
        long a = ftell(fp1);

        // fread返回的是整数块，不足一整块的不会被计入n
        // 但是是可以被正常读取
        // 例如读到96个字节，返回4
        // 例如读到46个字节，返回2
        // 例如读到16个字节，返回0
        int n = fread(buf, 20, 5, fp1);   // 按数据块（即可处理文本也可处理二进制）

        // a. 读取失败或到文件尾
        //    此时可能读取的数据量是 0-99 个字节
        if(n < 5)
        {
            if(feof(fp1))
            {
                // 将剩余的 0-99 个字节拷贝到目标文件
                // 提示：
                // ftell(fp1); // 获得当前文件位置
                // fseek();    // 调整文件位置
                // lseek();    // 调整并获得文件位置（系统IO）

                // 添加你的代码
                long b = ftell(fp1);
                fwrite(buf, b-a, 1, fp2);
                break;
            }

            if(ferror(fp1))
            {
                // 添加你的代码
                perror("读取文件失败");
                return -1;
            }
        }

        // b. 正常读到100个字节
        //    写入目标文件
        fwrite(buf, 20, 5, fp2);
    }

    // 3. 释放资源
    fclose(fp1);
    fclose(fp2);

    return 0;
}
